/**
 * @author zhengjiachao
 * @since 2017-4-11
 */
'use strict';
var fs = require('fs.extra');
var fssync = require('fs-sync');
var path = require('path');
var ejs = require('ejs');
var jsdom = require("jsdom");
var jquery = fs.readFileSync(path.join(__dirname, "thr/jquery.js"), "utf-8");

/**
 * 界面的html直接存储在设计结果的json当中，编译器直接使用这个html作为运行期要渲染的html。如果html还需要根据模型数据进行调整的话，也可以继续调整
 */

class BaseJSONCompiler{

    constructor(logger){
        this.logger = logger;
    }

    /**
     * 
     * @param {*string} jsonPath json文件的路径
     * @param {*string} bundleFolderPath 插件的路径
     * @param {*string} outputFolder 输出目录相对于插件路径的路径
     */
    compile(jsonPath, bundleFolderPath, outputFolder, callback){
        this.logger.debug('reading json file on ' + jsonPath);
        var jsonContent = fs.readFileSync(jsonPath, 'utf-8');
        var fullPath = path.join(bundleFolderPath, outputFolder);
        var thisObj = this;
        if(jsonContent){
            this.logger.debug('removing old output of ' + fullPath);
            fs.rmrf(fullPath,  (err)=> {
                if (!err) {
                    this.logger.debug('making dir of ' + fullPath);
                    fs.mkdirSync(fullPath);
                    var json = JSON.parse(jsonContent);
                    json.cachedModel = thisObj._getCachedModel(JSON.parse(json.designerData).contentData);
                    try{
                        this.logger.debug('generating HTML ');
                        thisObj._generateHTML(json, fullPath, function(){
                            this.logger.debug('generating Models ');
                            thisObj._generateModels(json, fullPath, outputFolder);
                            this.logger.debug('generating Builder ');
                            thisObj._generateBuilder(bundleFolderPath, json, fullPath);
                            callback();
                        }.bind(this));
                    }catch(e){
                        callback(e);
                    }
                }
            });
        }
    }

    _getCachedModel(diagram){
        var resolved = {};
        var resolve = function(control){
            var json = JSON.parse(control);
            resolved[json.id] = json;
            if(json.children){
                for(var i = 0; i < json.children.length; i++){
                    resolve(json.children[i]);
                }
            }
        }
        resolve(diagram);
        return resolved;
    }

    _generateHTML(json, fullPath, callback){
        jsdom.env({
            html: JSON.parse(json.designerData).htmlData,
            src : [jquery],
            done : function (err, window) {
                var $ = window.$;
                var document = window.document;
                var $globalEval = $.globalEval;
                var $_evalUrl = $._evalUrl;
                $.globalEval = $._evalUrl = function(){};
                this._compileHTML(json, $, document);
                $.globalEval = $globalEval;
                $._evalUrl = $_evalUrl;
                fs.writeFileSync(path.join(fullPath, 'block.html'), jsdom.serializeDocument(document));
                callback();
            }.bind(this)
        });
    }

    _compileHTML(json, $, document){
        $('.adf_wrapper').each(function(index,element){
            var $el = $(element);
            var child = $el.children()[0];
            $(child).attr("style",$el.attr("style"));
            $(child).attr("adftag",$el.attr("adftag"));
            $(child).attr("adfid",$el.attr("adfid"));
            $(child).attr("ADF_Control_Type",$el.attr("ADF_Control_Type"));
            $el.after(child);
            $el.remove();
        });
    }
    
    _generateModels(json, fullPath, outputFolder){
        var modelFolder = path.join(fullPath, 'model');
        fs.mkdirSync(modelFolder);
        var baseInfoData = json.baseInfoData;
        var formName = baseInfoData["blockName"];
        if(!formName){
            throw new Error("form名称不能为空");
        }
        this._generateBlockModel(formName, modelFolder, outputFolder);
        this._generateResModel(formName, modelFolder, outputFolder);
    }

    _generateBlockModel(formName, modelFolder, outputFolder){
        var rendered = this._renderEjs(this._getBlockEjsPath(), {formName : formName, outputFolder : outputFolder});
        fs.writeFileSync(path.join(modelFolder, 'block.block'), rendered);
    }
    
    _generateResModel(formName, modelFolder, outputFolder){
        var rendered = this._renderEjs(this._getResEjsPath(), {formName : formName, outputFolder : outputFolder});
        fs.writeFileSync(path.join(modelFolder, 'res.res'), rendered);
    }

    _generateBuilder(bundleFolderPath, json, fullPath){
        var publicPath = path.join(fullPath, 'public');
        fs.mkdirSync(publicPath);
        var rendered = this._renderEjs(this._getBuilderEjsPath(), this._getBuilderRenderAgrs(bundleFolderPath, json, fullPath));
        fs.writeFileSync(path.join(publicPath, 'builder.js'), rendered);
    }

    _getBuilderRenderAgrs(bundleFolderPath, json, fullPath){
        var baseInfoData = json.baseInfoData;
        var jsFilePath = baseInfoData["scriptPath"];
        if(!jsFilePath){
            throw new Error("js文件路径不能为空");
        }
        var jsContent = fs.readFileSync(path.join(bundleFolderPath, jsFilePath), 'utf-8');
        return {jsContent : jsContent, cachedModel : json.cachedModel};
    }

    _getBlockEjsPath(){
        return path.join(this._getEjsFolder(), 'block.ejs');
    }

    _getResEjsPath(){
        return path.join(this._getEjsFolder(), 'res.ejs');
    }

    _getBuilderEjsPath(){
        return path.join(this._getEjsFolder(), 'builder.ejs');
    }

    _getEjsFolder(){
        return path.join(__dirname, 'res');
    }
    

    _renderEjs(file, input){
        input.filename = file;
        var content = fs.readFileSync(file, 'utf-8');
        return ejs.render(content, input);
    }

}

module.exports = BaseJSONCompiler;